package com.yanhao.viewmode

import android.util.Log
import androidx.lifecycle.*
import com.yanhao.bean.ApiResult
import com.yanhao.bean.Article
import com.yanhao.bean.BannerData
import com.yanhao.bean.ResultViewState
import com.yanhao.etx.ErrorData
import com.yanhao.etx.error
import com.yanhao.repository.HomeFgRepository
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

typealias Error = suspend (e: ErrorData) -> Unit

class HomeFgViewModel(private val resp: HomeFgRepository) : BaseViewModel() {

    private var _count = MutableStateFlow(0)
    val count = _count.asStateFlow()

    fun plus() {
        val temp = _count.value
        _count.value = temp.plus(1)
    }

    fun minus() {
        val temp = _count.value
        _count.value = temp.minus(1)
    }


    private var _currentPageIndex = MutableLiveData<Int>(0)
    val currentPageIndex: LiveData<Int> = _currentPageIndex

//    private var _bannerData: MutableLiveData<List<BannerData>> = MutableLiveData()
//    val bannerData: LiveData<List<BannerData>> = _bannerData
//
//    private var _bannerData = MutableStateFlow<MutableList<BannerData>>(mutableListOf())
//    val bannerData: StateFlow<MutableList<BannerData>> = _bannerData

//    private var _bannerData: MutableLiveData<ApiResult<MutableList<BannerData>>> = MutableLiveData()
//    val bannerData: LiveData<ApiResult<MutableList<BannerData>>> = _bannerData

    private var _bannerData: MutableLiveData<ResultViewState<MutableList<BannerData>>> = MutableLiveData()
    val bannerData: LiveData<ResultViewState<MutableList<BannerData>>> = _bannerData

    private var _homeArticles = MutableLiveData<MutableList<Article>>()
    val homeArticles: LiveData<MutableList<Article>> = _homeArticles

//    private var _homeArticles = MutableStateFlow<MutableList<Article>>()
//    val homeArticles: StateFlow<MutableList<Article>> = _homeArticles

    private var _bannerErrMsg: MutableLiveData<String> = MutableLiveData()
    val bannerErrMsg: LiveData<String> = _bannerErrMsg

    private var exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
        Log.e("TAG", "coroutineContext= ${coroutineContext} \n throwable= ${throwable}")
    }

    fun getBanner() {
        //TODO 1
//        launch {
//            flow {
//                var banner = resp.getBanner()
//                emit(banner)
//            }.onStart {
//
//            }.catch { e:Throwable ->
//                errorCatch(e)
//            }.onCompletion {
//
//            }.collect {
//                if (it.errorCode == 0) {
//                    _bannerData.postValue(it.data)
//                }
//            }
//        }

        //TODO 2
//        launch {
//            var banner = resp.getBanner()
//            Log.e("TAG", "当前线程${Thread.currentThread().name} 结果是:${banner} ")
//            if (banner.errorCode == 0) {
//                _bannerData.postValue(banner.data)
//            }
//        }

        //TODO 3
//        viewModelScope.launch(exceptionHandler) {
//            var banner = resp.getBanner()
//            if (banner.errorCode == 0) {
//                _bannerData.postValue(banner.data)
//            }
//        }
        //TODO 4
//        viewModelScope.launch {
//            runCatching {
//                resp.getBanner()
//            }.onFailure {
//                val errorData = it.error()
//                errorData?.let {
//                    _bannerErrMsg.value = errorData.msg
//                }
//            }.onSuccess {
//                if (it.errorCode == 0) {
//                    _bannerData.postValue(it.data)
//                }
//            }
//        }

        //TODO 5
//        launch(
//            block = {
//                resp.getBanner()
//            },
//            success = {
//                if (it.errorCode == 0) {
//                    _bannerData.value = it.data
//                }
//            },
//            error = {
//                it?.let {
//                    _bannerErrMsg.value = it.msg
//                }
//            }
//        )

        //TODO 6
        //密封类处理数据结果
        viewModelScope.launch {
            resp.getBanner().onStart {
//                _bannerData.value = ApiResult.Loadding
                _bannerData.value = ResultViewState(state =ApiResult.Loadding )
            }.catch { e ->
                val errorData = e.error()
//                errorData?.let {
//                    _bannerErrMsg.value = errorData.msg
//                }
                errorData?.let {
//                    _bannerData.value =
//                        ApiResult.Faiure(errorCode = errorData.code, errorMsg = errorData.msg)
                    _bannerData.value = ResultViewState(state =ApiResult.Faiure(errorCode = errorData.code, errorMsg = errorData.msg) )
                }
            }.onCompletion {
//                _bannerData.value = ApiResult.Completion
                _bannerData.value = ResultViewState(state =ApiResult.Completion)
            }.collectLatest {
                if (it.errorCode == 0) {
//                    _bannerData.value =
//                        ApiResult.Success(it.data)
                    _bannerData.value = ResultViewState(state =ApiResult.Success(it.data))
                } else {
//                    _bannerData.value =
//                        ApiResult.Faiure(errorCode = it.errorCode, errorMsg = it.errorMsg)
                    _bannerData.value = ResultViewState(state =ApiResult.Faiure(errorCode = it.errorCode, errorMsg = it.errorMsg))
                }
            }
        }
    }

    fun <T> launch(
        block: suspend () -> T,
        success: suspend (T) -> Unit,
        error: Error? = null
    ) {
        viewModelScope.launch {
            runCatching {
                block()
            }.onFailure { e: Throwable ->
                errorCatch(e)
            }.onSuccess {
                success(it)
            }
        }
    }


    fun getHomeAndTopArticels() {
        viewModelScope.launch {
            supervisorScope {
                try {
                    var resultList = mutableListOf<Article>()
                    val mainArticle = async {
                        resp.getHomeArticels(0)
                    }
                    val topArticle = async {
                        resp.getTopArticels()
                    }
//            Log.e("TAG", "mainArticle: ${mainArticle.await()}")
//            Log.e("TAG", "topArticle : ${topArticle.await()} ")
//            Log.e("TAG", "========================= ")
                    resultList.addAll(topArticle.await().data)
                    resultList.addAll(mainArticle.await().data.datas)
                    _homeArticles.value = resultList
                } catch (e: Throwable) {
                    errorCatch(e)
                }
            }
        }
    }

//    val more = flow {
//        val result = resp.getHomeArticels(_currentPageIndex.value ?: 0)
//        emit(result)
//    }.flowOn(Dispatchers.IO).map {
//        val datas = it.data.datas
//        val result: MutableList<Article> = mutableListOf()
//        if (!datas.isEmpty()) {
//            result.addAll(datas)
//        }
////                    Log.e("TAG", "--> 处理 线程运行在:${Thread.currentThread().name} result=: ${result} ")
//        result
//    }.flowOn(Dispatchers.IO)
//        .catch { e: Throwable ->
//            errorCatch(e)
//        }

    fun getHomeArticels() {
        viewModelScope.launch {
            flow {
                val result = resp.getHomeArticels(_currentPageIndex.value ?: 0)
//                Log.e("TAG", "--> 发射 线程运行在:${Thread.currentThread().name}")
                emit(result)
            }.flowOn(Dispatchers.IO)
                .onStart {

                }.catch {

                }.onCompletion {

                }.collect {
//                    Log.e("TAG", "--> 结果 线程运行在:${Thread.currentThread().name} 接收到的文章数据是:${it} ")
                    it?.apply {
                        Log.e("TAG", "map后的结果是:${this} ")
                        val currentIndex = _currentPageIndex.value
                        if (currentIndex == 0) {
                            _homeArticles.value = this.data.datas
                        } else {
                            val list = _homeArticles.value
                            list?.addAll(this.data.datas)
                            list?.let {
                                _homeArticles.value = it
                            }
                            Log.e("TAG", "m结果是:${_homeArticles.value} ")
                        }
                    }
                }
        }
    }


    fun launch(block: suspend () -> Unit) {
        try {
            viewModelScope.launch {
                block()
            }
        } catch (e: Exception) {
            Log.e("TAG", "错误是:${e.message}")
        }
    }

    fun collectArticle(id: Int) {
        var value = _homeArticles.value
        value?.map {
            if (id == it.id) {
                if (it.collect) {
                    it.copy(collect = false)
                } else {
                    it.copy(collect = true)
                }
            } else {
                it
            }
        }?.toMutableList().let {
            _homeArticles.value = it
        }
    }

    fun refreshCurrent() {
        _currentPageIndex.value = 0
        getHomeAndTopArticels()
    }

    fun onLoadMoreCurrent() {
        val index = _currentPageIndex.value ?: 0
        val result = index.plus(1)
        _currentPageIndex.value = result
        getHomeArticels()
    }

}

class HomeFgViewModelFactory() : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(HomeFgViewModel::class.java)) {
            return HomeFgViewModel(resp = HomeFgRepository()) as T
        }
        throw IllegalArgumentException("不能找到 HomeFgRepository")
    }

}